package com.wlyuan.index.domain.index.builder;

import com.wlyuan.core.marker.NamedUtils;
import com.wlyuan.core.marker.ValueUtils;
import com.wlyuan.index.api.dto.order.OrderIndexDTO;
import com.wlyuan.index.domain.index.OrderIndex;
import com.wlyuan.index.domain.source.utils.SourceUtils;
import com.wlyuan.order.vo.OrderDeviceVO;
import com.wlyuan.order.vo.TimeoutWarnVO;
import lombok.var;
import org.apache.commons.lang3.BooleanUtils;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.Mappings;
import org.mapstruct.factory.Mappers;

import java.time.LocalDateTime;
import java.util.Optional;

/**
 * @author yuanjie
 */
public class OrderIndexBuilder {

    @Mapper(uses = {SourceUtils.class, ValueUtils.class, NamedUtils.class})
    interface Assembler {

        @Mappings({
                @Mapping(target = "fromContactName", source = "source.fromAddress.contactName"),
                @Mapping(target = "fromContactMobile", source = "source.fromAddress.contactMobile"),
                @Mapping(target = "fromAddress", source = "source.fromAddress.address"),
                @Mapping(target = "fromProvince", source = "source.fromAddress.province"),
                @Mapping(target = "fromProvinceCode", source = "source.fromAddress.provinceCode"),
                @Mapping(target = "fromCity", source = "source.fromAddress.city"),
                @Mapping(target = "fromCityCode", source = "source.fromAddress.cityCode"),
                @Mapping(target = "fromDistrict", source = "source.fromAddress.district"),
                @Mapping(target = "fromDistrictCode", source = "source.fromAddress.districtCode"),
                @Mapping(target = "toContactName", source = "source.toAddress.contactName"),
                @Mapping(target = "toContactMobile", source = "source.toAddress.contactMobile"),
                @Mapping(target = "toProvince", source = "source.toAddress.province"),
                @Mapping(target = "toProvinceCode", source = "source.toAddress.provinceCode"),
                @Mapping(target = "toCity", source = "source.toAddress.city"),
                @Mapping(target = "toCityCode", source = "source.toAddress.cityCode"),
                @Mapping(target = "toDistrict", source = "source.toAddress.district"),
                @Mapping(target = "toDistrictCode", source = "source.toAddress.districtCode"),
                @Mapping(target = "toAddress", source = "source.toAddress.address"),
                @Mapping(target = "lastWarnAt", source = "source.device.warnAt"),
                @Mapping(target = "signType", source = "source.sign.signType"),
                @Mapping(target = "id", source = "orderId")
        })
        OrderIndex assemble(OrderIndexDTO source);
    }

    private final OrderIndexDTO order;
//    private final OrderStrategies strategies;

    public OrderIndexBuilder(OrderIndexDTO order) {
        this.order = order;
//        this.strategies = strategies;
    }

    private static final Assembler ASSEMBLER = Mappers.getMapper(Assembler.class);

    public OrderIndex build() {
        var index = ASSEMBLER.assemble(this.order);
        index.setHasDevice(this.order.getHasDevice());
        index.setHasCert(this.order.getHasCert());
        index.setGenerateCert(this.order.getGenerateCert());
//        var strategy = this.strategies.get(this.order.getTenantId());
//        if (strategy != null) {
//            index.setBusinessNos(strategy.process(this.order));
//        }

        Integer arrivalPlan;
        if (BooleanUtils.isTrue(this.order.getArriveDelayed())) {
            arrivalPlan = 2;
        } else {
            arrivalPlan = Optional.ofNullable(this.order.getDevice())
                    .map(OrderDeviceVO::getWarning)
                    .map(TimeoutWarnVO::getTimeout)
                    .orElse(null);
        }

        index.setArrivalPlan(arrivalPlan);
        var overdueNoSign = order.getDelayed() && !order.getSigned();
        index.setOverdueNoSign(overdueNoSign);
        index.setIndexAt(LocalDateTime.now());
        return index;
    }
}
